package util.thread.ordertoperform;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * @Description：
 * @Author：LiDong
 * @Create：2020/12/2
 * @Version：1.0.0
 */
public class CyclicBarrierTest {

    private static final Logger logger = LoggerFactory.getLogger(CyclicBarrierTest.class);

    private final CyclicBarrier barrier1 = new CyclicBarrier(2);
    private final CyclicBarrier barrier2 = new CyclicBarrier(2);

    private CyclicBarrier cyclicBarrier = new CyclicBarrier(3);

    class One extends Thread {
        @Override
        public void run() {
            try {
                logger.info("=====》One线程执行完成...");
                // 放开栅栏1
                barrier1.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                logger.error(e.getMessage(), e);
            }
        }
    }


    class Two extends Thread {
        @Override
        public void run() {
            try {
                // 放开栅栏1
                barrier1.await();
                logger.info("=====》Two线程执行完成...");
                // 放开栅栏2
                barrier2.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                logger.error(e.getMessage(), e);
            }
        }
    }

    class Three extends Thread {
        @Override
        public void run() {
            // 放开栅栏2
            try {
                barrier2.await();
                logger.info("======》Three线程执行完成...");
            } catch (InterruptedException | BrokenBarrierException e) {
                logger.error(e.getMessage(), e);
            }
        }
    }

    @Test
    public void test1() throws InterruptedException {
        Thread one = new One();
        one.start();

        Thread two = new Two();
        two.start();

        Thread three = new Three();
        three.start();

        Thread.sleep(5000);
        logger.info("=====>三个子线程结束...");
    }

    @Test
    public void test2() {
        List<Athlete> athleteList = new ArrayList<>();
        athleteList.add(new Athlete(cyclicBarrier, "博尔特"));
        athleteList.add(new Athlete(cyclicBarrier, "鲍威尔"));
        athleteList.add(new Athlete(cyclicBarrier, "盖伊"));
        Executor executor = Executors.newFixedThreadPool(8);
        for (Athlete athlete : athleteList) {
            executor.execute(athlete);
        }
        logger.info("所有运动员就位了...");
    }

    class Athlete implements Runnable {

        private CyclicBarrier cyclicBarrier;
        private String name;

        public Athlete(CyclicBarrier cyclicBarrier, String name) {
            this.cyclicBarrier = cyclicBarrier;
            this.name = name;
        }

        @Override
        public void run() {
            logger.info("运动员 {} 就位", name);
            try {
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                logger.error(e.getMessage(), e);
            }
        }
    }
}
